package judesart.app.client.ui.admin.artwork;

import gwtupload.client.IUploader;
import gwtupload.client.MultiUploader;
import gwtupload.client.PreloadedImage;
import gwtupload.client.IFileInput.AnchorFileInput;
import gwtupload.client.IUploadStatus.Status;
import gwtupload.client.IUploader.OnFinishUploaderHandler;
import gwtupload.client.IUploader.OnStartUploaderHandler;
import gwtupload.client.PreloadedImage.OnLoadPreloadedImageHandler;

import java.util.Arrays;
import java.util.List;

import judesart.app.client.controller.ArtworkController;
import judesart.app.client.controller.ArtworkControllerAsync;
import judesart.app.client.controller.ExhibitionController;
import judesart.app.client.controller.ExhibitionControllerAsync;
import judesart.app.client.controller.GalleryController;
import judesart.app.client.controller.GalleryControllerAsync;
import judesart.app.client.controller.ProjectController;
import judesart.app.client.controller.ProjectControllerAsync;
import judesart.app.client.model.ArtworkTypeModel;
import judesart.app.client.resources.Resources;
import judesart.app.client.widget.TopInfo;
import judesart.app.domain.Artwork;
import judesart.app.domain.ArtworkPhoto;
import judesart.app.domain.Exhibition;
import judesart.app.domain.ExhibitionArtwork;
import judesart.app.domain.Gallery;
import judesart.app.domain.Room;
import judesart.app.domain.RoomArtwork;
import judesart.app.shared.SearchResult;
import judesart.app.shared.SelectProject;

import com.allen_sauer.gwt.log.client.Log;
import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
import com.extjs.gxt.ui.client.event.BaseEvent;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.FieldSetEvent;
import com.extjs.gxt.ui.client.event.IconButtonEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.MenuEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.Composite;
import com.extjs.gxt.ui.client.widget.Info;
import com.extjs.gxt.ui.client.widget.Label;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.button.ButtonBar;
import com.extjs.gxt.ui.client.widget.button.ToolButton;
import com.extjs.gxt.ui.client.widget.form.CheckBox;
import com.extjs.gxt.ui.client.widget.form.ComboBox;
import com.extjs.gxt.ui.client.widget.form.FieldSet;
import com.extjs.gxt.ui.client.widget.form.FormPanel;
import com.extjs.gxt.ui.client.widget.form.HtmlEditor;
import com.extjs.gxt.ui.client.widget.form.LabelField;
import com.extjs.gxt.ui.client.widget.form.MultiField;
import com.extjs.gxt.ui.client.widget.form.NumberField;
import com.extjs.gxt.ui.client.widget.form.TextField;
import com.extjs.gxt.ui.client.widget.form.ComboBox.TriggerAction;
import com.extjs.gxt.ui.client.widget.form.FormPanel.LabelAlign;
import com.extjs.gxt.ui.client.widget.layout.ColumnData;
import com.extjs.gxt.ui.client.widget.layout.ColumnLayout;
import com.extjs.gxt.ui.client.widget.layout.FormData;
import com.extjs.gxt.ui.client.widget.layout.FormLayout;
import com.extjs.gxt.ui.client.widget.menu.Menu;
import com.extjs.gxt.ui.client.widget.menu.MenuItem;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;

public class ArtworkDetailsPanel extends Composite {
    private final IUploader.OnFinishUploaderHandler onFinishUploaderHandler = new IUploader.OnFinishUploaderHandler() {
        public void onFinish(IUploader uploader) {
            if (uploader.getStatus() == Status.SUCCESS) {
                new PreloadedImage(uploader.fileUrl(), showImage);
            }
        }
    };

    private final OnLoadPreloadedImageHandler showImage = new OnLoadPreloadedImageHandler() {
        public void onLoad(PreloadedImage image) {
            addImageToPanel(image);
        }
    };

    // A panel where the thumbnails of uploaded images will be shown
    private LayoutContainer panelImages;

    ArtworkControllerAsync artworkController = GWT.create(ArtworkController.class);
    ProjectControllerAsync projectController = GWT.create(ProjectController.class);
    GalleryControllerAsync galleryController = GalleryController.Util.getInstance();
    ExhibitionControllerAsync exhibitionController = ExhibitionController.Util.getInstance();

    private final FormPanel frmpnlArtwork;
    private FieldSet fldstBasic;
    private FieldSet fldstDetail;
    private FieldSet fldstPhotos;
    private TextField<String> txtfldTitle;
    private HtmlEditor htmldtrDetail;
    private ComboBox<ArtworkTypeModel> cmbxType;
    private NumberField nmbrfldYear;
    private NumberField nmbrfldWidth;
    private NumberField nmbrfldHeight;
    private TextField<String> txtfldTech;
    private TextField<String> txtfldTags;
    private CheckBox chbxForSale;
    private CheckBox chbxFeatured;
    private NumberField nmbrfldPrice;
    private final ArtworksPanel parent;
    private Artwork artwork = new Artwork();
    private final Button btnAddToProject;
    private final Button btnAddToGallery;
    private final Button btnAddToExhibition;

    private LabelField lblfldEuros;

    private LabelField lblfldPrice;

    public ArtworkDetailsPanel(ArtworksPanel parent) {
        this.parent = parent;

        frmpnlArtwork = new FormPanel();
        frmpnlArtwork.setLabelSeparator("");
        frmpnlArtwork.setLabelAlign(LabelAlign.TOP);
        frmpnlArtwork.setHeading("Artwork");
        frmpnlArtwork.setFrame(true);
        frmpnlArtwork.setButtonAlign(HorizontalAlignment.CENTER);

        ButtonBar topBar = new ButtonBar();
        btnAddToProject = new Button("Projects");
        btnAddToProject.setEnabled(false);
        final Menu menu = new Menu();
        btnAddToProject.setMenu(menu);
        setProjectsInAddButton();
        topBar.add(btnAddToProject);

        btnAddToGallery = new Button("Galleries");
        btnAddToGallery.setEnabled(false);
        final Menu galleryMenu = new Menu();
        btnAddToGallery.setMenu(galleryMenu);
        setGalleriesInAddButton();
        topBar.add(btnAddToGallery);

        btnAddToExhibition = new Button("Exhibitions");
        btnAddToExhibition.setEnabled(false);
        final Menu exhibitionMenu = new Menu();
        btnAddToExhibition.setMenu(exhibitionMenu);
        setExhibitionsInAddButton();
        topBar.add(btnAddToExhibition);

        topBar.setAlignment(HorizontalAlignment.LEFT);
        frmpnlArtwork.add(topBar);

        initBasicFieldSet();

        initDetailFieldSet();

        initPhotosFielsSet();

        Button btnDelete = new Button("Delete");
        frmpnlArtwork.addButton(btnDelete);

        btnDelete.addListener(Events.Select, new Listener<ButtonEvent>() {
            @Override
            public void handleEvent(ButtonEvent be) {
                delete();
            }
        });

        Button btnSave = new Button("Save");
        frmpnlArtwork.addButton(btnSave);

        Button btnCancel = new Button("Cancel");
        frmpnlArtwork.addButton(btnCancel);

        btnSave.addListener(Events.Select, new Listener<ButtonEvent>() {
            public void handleEvent(ButtonEvent e) {
                save();
            }
        });
        btnCancel.addListener(Events.Select, new Listener<ButtonEvent>() {
            public void handleEvent(ButtonEvent e) {
                cancel();
            }
        });

        frmpnlArtwork.setSize("800px", "515px");

        fldstBasic.setExpanded(true);
        fldstDetail.setExpanded(true);
        fldstPhotos.setExpanded(false);

        initComponent(frmpnlArtwork);
    }

    private void setProjectsInAddButton() {
        btnAddToProject.setEnabled(false);
        btnAddToProject.getMenu().removeAll();
        if (artwork == null || artwork.getArtistId() == null) {
            return;
        }
        artworkController.getSelectProjectValues(artwork.getId(),
                new AsyncCallback<List<SelectProject>>() {
                    @Override
                    public void onFailure(Throwable caught) {
                        Log.error("Unable to get projects", caught);
                        btnAddToProject.setEnabled(false);
                    }

                    @Override
                    public void onSuccess(List<SelectProject> result) {
                        addProjectsToMenu(result);
                    }
                });
    }

    private void setGalleriesInAddButton() {
        btnAddToGallery.setEnabled(false);
        btnAddToGallery.getMenu().removeAll();
        if (artwork == null || artwork.getArtistId() == null) {
            return;
        }
        galleryController.searchGalleries(0, 100,
                new AsyncCallback<SearchResult<Gallery>>() {
                    @Override
                    public void onFailure(Throwable caught) {
                        Log.error("Unable to get galleries", caught);
                        btnAddToGallery.setEnabled(false);
                    }

                    public void onSuccess(SearchResult<Gallery> result) {
                        addGalleriesToMenu(result.getResults());
                    };
                });
    }

    private void setExhibitionsInAddButton() {
        btnAddToExhibition.setEnabled(false);
        btnAddToExhibition.getMenu().removeAll();
        if (artwork == null || artwork.getArtistId() == null) {
            return;
        }
        exhibitionController.searchExhibitions(0, 100,
                new AsyncCallback<SearchResult<Exhibition>>() {
                    @Override
                    public void onFailure(Throwable caught) {
                        Log.error("Unable to get galleries", caught);
                        btnAddToExhibition.setEnabled(false);
                    }

                    public void onSuccess(SearchResult<Exhibition> result) {
                        addExhibitionsToMenu(result.getResults());
                    };
                });
    }

    public void open(Long artworkId) {
        clearAndDisableAll();
        if (artworkId != null) {
            artworkController.getArtwork(artworkId,
                    new AsyncCallback<Artwork>() {
                        @Override
                        public void onFailure(Throwable caught) {
                            Info.display("Error", "Problem updating artwork.");
                            cancel();
                        }

                        @Override
                        public void onSuccess(Artwork result) {
                            showDetails(result);
                        }
                    });
        } else {
            showDetails(new Artwork());
        }
    }

    private void showDetails(Artwork artwork) {
        this.artwork = artwork;
        txtfldTitle.setValue(artwork.getTitle());
        txtfldTitle.enable();
        htmldtrDetail.setValue(artwork.getDescription());
        htmldtrDetail.enable();
        cmbxType.setValue(ArtworkTypeModel.valueOf(artwork.getType()));
        nmbrfldYear.setValue(artwork.getYear());
        if (artwork.getDimensions() != null) {
            String[] dimensions = artwork.getDimensions().split("x");
            if (dimensions.length > 1) {
                nmbrfldWidth.setValue(new Integer(dimensions[0]));
                nmbrfldHeight.setValue(new Integer(dimensions[1]));
            }
        }
        txtfldTech.setValue(artwork.getTechnic());
        String tags = "";
        List<String> tagsList = artwork.getTags();
        if (tagsList != null) {
            for (String string : tagsList) {
                tags += " " + string;
            }
            txtfldTags.setValue(tags.trim());
        }
        chbxForSale.setValue(artwork.getForSale());
        nmbrfldPrice.setValue(artwork.getPrice());
        fldstDetail.enable();
        fldstPhotos.enable();
        if (artwork.getPhotos() != null) {
            Log.debug(" > success [" + artwork.getPhotos() + "]");
            List<ArtworkPhoto> photos = artwork.getPhotos();
            for (ArtworkPhoto photo : photos) {
                String url = "/image/" + photo.getImageId() + "_75x75";
                Log.debug(" > success image url [" + url + "]");
                new PreloadedImage(url, photo.getImageId().toString(), "photo_"
                        + photo.getImageId(), showImage);
            }
        }
        chbxFeatured.setValue(artwork.getFeatured());
        setProjectsInAddButton();
        setGalleriesInAddButton();
        setExhibitionsInAddButton();
    }

    private void clearAndDisableAll() {
        txtfldTitle.clear();
        txtfldTitle.disable();
        htmldtrDetail.clear();
        htmldtrDetail.disable();
        fldstDetail.collapse();
        fldstPhotos.collapse();
        fldstPhotos.disable();
        fldstBasic.expand();
        cmbxType.clear();
        nmbrfldYear.clear();
        nmbrfldHeight.clear();
        nmbrfldWidth.clear();
        txtfldTech.clear();
        txtfldTags.clear();
        panelImages.removeAll();
        panelImages.layout();
    }

    private void delete() {

        artworkController.deleteArtwork(artwork.getId(),
                new AsyncCallback<Void>() {
                    @Override
                    public void onFailure(Throwable caught) {
                        TopInfo.display("Error", "Unable to delete artwork.");
                    }

                    @Override
                    public void onSuccess(Void result) {
                        cancel();
                    }
                });
    }

    private void save() {
        artwork.setTitle(txtfldTitle.getValue());
        artwork.setDescription(htmldtrDetail.getValue());
        artwork.setYear(nmbrfldYear.getValue().longValue());
        artwork.setTechnic(txtfldTech.getValue());
        artwork.setType(cmbxType.getValue().getType());
        artwork.setTags(Arrays.asList(txtfldTags.getValue().split(" ")));
        artwork.setDimensions(nmbrfldWidth.getValue().toString() + "x"
                + nmbrfldHeight.getValue().toString());
        artwork.setForSale(chbxForSale.getValue());
        artwork.setPrice(nmbrfldPrice.getValue().doubleValue());
        artwork.setFeatured(chbxFeatured.getValue());

        if (artwork.getId() == null) {
            artworkController.createArtwork(artwork,
                    new AsyncCallback<Artwork>() {
                        @Override
                        public void onSuccess(Artwork result) {
                            Info.display("Info", "Artwork created.");
                            showDetails(result);
                        }

                        @Override
                        public void onFailure(Throwable caught) {
                            Info.display("Error", "Problem creating artwork.");
                        }
                    });
        } else {
            artworkController.updateArtwork(artwork,
                    new AsyncCallback<Artwork>() {
                        @Override
                        public void onSuccess(Artwork result) {
                            Info.display("Info", "Artwork updated.");
                            showDetails(result);
                        }

                        @Override
                        public void onFailure(Throwable caught) {
                            Info.display("Error", "Problem updating artwork.");
                        }
                    });
        }
    }

    private void cancel() {
        parent.showList();
    }

    private void addImageToPanel(final PreloadedImage image) {
        image.setWidth("75px");
        final LayoutContainer imageContainer = new LayoutContainer();
        imageContainer.add(image);
        final ToolButton deletePhotoButton = new ToolButton(".x-tool-close");
        final Long artworkId = artwork.getId();
        deletePhotoButton.addListener(Events.Select,
                new Listener<IconButtonEvent>() {
                    public void handleEvent(IconButtonEvent e) {
                        imageContainer.setEnabled(false);
                        artworkController.deletePhotoFromArtwork(artworkId,
                                new Long(image.getUniqId()),
                                new AsyncCallback<Void>() {
                                    @Override
                                    public void onFailure(Throwable caught) {
                                        TopInfo.display("Error",
                                                "Unable to delete image");
                                        imageContainer.setEnabled(true);
                                    }

                                    @Override
                                    public void onSuccess(Void result) {
                                        TopInfo.display("Info",
                                                "Image deleted succeffuly");
                                        imageContainer.setVisible(false);
                                    }
                                });
                    }
                });
        deletePhotoButton.setVisible(false);
        imageContainer.add(deletePhotoButton);
        final Timer hideDeletePhotoTime = new Timer() {
            @Override
            public void run() {
                deletePhotoButton.setVisible(false);
            }
        };
        image.addMouseOverHandler(new MouseOverHandler() {
            public void onMouseOver(MouseOverEvent event) {
                hideDeletePhotoTime.cancel();
                deletePhotoButton.setVisible(true);
            }
        });
        image.addMouseOutHandler(new MouseOutHandler() {
            public void onMouseOut(MouseOutEvent event) {
                hideDeletePhotoTime.schedule(2000);
            }
        });
        imageContainer.setWidth("95px");
        panelImages.add(imageContainer);
        panelImages.layout();
    }

    private void initPhotosFielsSet() {
        fldstPhotos = new FieldSet();
        fldstPhotos.setHeight(300);
        fldstPhotos.addListener(Events.Expand, new Listener<FieldSetEvent>() {
            public void handleEvent(FieldSetEvent e) {
                fieldSetExpand(e);
            }
        });

        panelImages = new LayoutContainer();
        panelImages.setBorders(false);
        panelImages.setLayout(new ColumnLayout());
        panelImages.setStyleAttribute("margin-bottom", "30px");
        fldstPhotos.add(panelImages);

        MultiUploader defaultUploader = new MultiUploader();

        defaultUploader.addOnFinishUploadHandler(onFinishUploaderHandler);
        defaultUploader.setMaximumFiles(10);
        defaultUploader.setFileInputPrefix("default");
        defaultUploader.setServletPath("/upload");
        defaultUploader.avoidRepeatFiles(true);
        defaultUploader.setFileInput(new AnchorFileInput());
        defaultUploader.addOnStartUploadHandler(new OnStartUploaderHandler() {
            @Override
            public void onStart(IUploader uploader) {
                if (getArtwork().getId() == null || getArtwork().getId() <= 0) {
                    save();
                }
                uploader.setServletPath("/upload");
            }
        });
        defaultUploader.addOnFinishUploadHandler(new OnFinishUploaderHandler() {

            @Override
            public void onFinish(IUploader uploader) {
                TopInfo.display("Info", "Upload : "
                        + uploader.getStatus().name());
                RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, "/commitimages?action=addToArtwork&id="
                        + getArtwork().getId());
                try {
                    builder.sendRequest(null, new RequestCallback() {

                        @Override
                        public void onResponseReceived(Request request,
                                Response response) {
                        }

                        @Override
                        public void onError(Request request, Throwable exception) {
                            Log.error("Error sending commit request", exception);
                            TopInfo.display("Error", "Unable to add images");
                        }
                    });
                } catch (RequestException e) {
                    Log.error("Error sending commit request", e);
                    TopInfo.display("Error", "Unable to add images");
                }
            }
        });

        fldstPhotos.add(defaultUploader);

        frmpnlArtwork.add(fldstPhotos);
        fldstPhotos.setHeading("Photos");
        fldstPhotos.setCollapsible(true);
    }

    public Artwork getArtwork() {
        return this.artwork;
    }

    private void initDetailFieldSet() {
        fldstDetail = new FieldSet();
        fldstDetail.addListener(Events.Expand, new Listener<FieldSetEvent>() {
            public void handleEvent(FieldSetEvent e) {
                fieldSetExpand(e);
            }
        });
        fldstDetail.setLayout(newFormLayout());

        LayoutContainer main = new LayoutContainer(new ColumnLayout());
        LayoutContainer left = new LayoutContainer(newFormLayout());
        main.add(left, new ColumnData(.33));
        LayoutContainer right = new LayoutContainer(newFormLayout());
        right.setStyleAttribute("padding-left", "1em");
        main.add(right, new ColumnData(.5));
        fldstDetail.add(main, new FormData("100%"));

        cmbxType = new ComboBox<ArtworkTypeModel>();
        cmbxType.setAllowBlank(false);
        cmbxType.setName("type");
        cmbxType.setDisplayField("value");
        cmbxType.setTypeAhead(true);
        cmbxType.setTriggerAction(TriggerAction.ALL);
        cmbxType.setEmptyText("Select a type...");
        ListStore<ArtworkTypeModel> ls = new ListStore<ArtworkTypeModel>();
        ls.add(ArtworkTypeModel.values());
        cmbxType.setStore(ls);
        cmbxType.setFieldLabel("type");
        left.add(cmbxType, new FormData("100%"));

        nmbrfldYear = new NumberField();
        nmbrfldYear.setAllowDecimals(false);
        nmbrfldYear.setAllowNegative(false);
        nmbrfldYear.setAllowBlank(false);
        nmbrfldYear.setMinLength(4);
        nmbrfldYear.setMaxLength(4);
        nmbrfldYear.setName("year");
        nmbrfldYear.setSize("80px", "20px");
        nmbrfldYear.setFieldLabel("year");
        right.add(nmbrfldYear, new FormData("50%"));

        MultiField mltfldSize = new MultiField();
        mltfldSize.setName("size");

        nmbrfldWidth = new NumberField();
        nmbrfldWidth.setAllowNegative(false);
        nmbrfldWidth.setAllowDecimals(false);
        nmbrfldWidth.setAllowBlank(false);
        nmbrfldWidth.setName("width");
        nmbrfldWidth.setMinLength(1);
        nmbrfldWidth.setMaxLength(3);
        mltfldSize.add(nmbrfldWidth);

        LabelField lblfldX = new LabelField("x");
        mltfldSize.add(lblfldX);

        nmbrfldHeight = new NumberField();
        nmbrfldHeight.setAllowNegative(false);
        nmbrfldHeight.setAllowDecimals(false);
        nmbrfldHeight.setAllowBlank(false);
        nmbrfldHeight.setName("height");
        nmbrfldHeight.setMinLength(1);
        nmbrfldHeight.setMaxLength(3);
        mltfldSize.add(nmbrfldHeight);

        LabelField lblfldCm = new LabelField("cm");
        mltfldSize.add(lblfldCm);
        mltfldSize.setFieldLabel("size");
        right.add(mltfldSize, new FormData("100%"));

        txtfldTech = new TextField<String>();
        txtfldTech.setAllowBlank(false);
        txtfldTech.setName("technic");
        txtfldTech.setFieldLabel("technic");
        left.add(txtfldTech, new FormData("100%"));

        txtfldTags = new TextField<String>();
        txtfldTags.setWidth(400);
        txtfldTags.setFieldLabel("tags");
        txtfldTags.setName("tags");
        txtfldTags.setToolTip("Tags separated by spaces.");
        right.add(txtfldTags, new FormData("100%"));

        MultiField<Number> mltfldSale = new MultiField<Number>();
        mltfldSale.setFieldLabel("for sale");
        chbxForSale = new CheckBox();
        chbxForSale.addListener(Events.Change, new Listener<BaseEvent>() {
            public void handleEvent(BaseEvent be) {
                onChangeChbxForSale(be);
            };
        });
        mltfldSale.add(chbxForSale);
        lblfldPrice = new LabelField(" price ");
        lblfldPrice.setVisible(false);
        lblfldPrice.setStyleAttribute("padding-left", "1em");
        mltfldSale.add(lblfldPrice);
        nmbrfldPrice = new NumberField();
        nmbrfldPrice.setVisible(false);
        nmbrfldPrice.setAllowBlank(true);
        nmbrfldPrice.setAllowDecimals(true);
        nmbrfldPrice.setAllowNegative(false);
        mltfldSale.add(nmbrfldPrice);
        lblfldEuros = new LabelField("&euro;");
        lblfldEuros.setVisible(false);
        lblfldEuros.setStyleAttribute("padding-left", "5px");
        mltfldSale.add(lblfldEuros);

        left.add(mltfldSale, new FormData("100%"));
        
        chbxFeatured = new CheckBox();
        chbxFeatured.setFieldLabel("featured");
        left.add(chbxFeatured, new FormData("8%"));

        frmpnlArtwork.add(fldstDetail);
        fldstDetail.setHeading("Detail");
        fldstDetail.setCollapsible(true);
    }

    private FormLayout newFormLayout() {
        FormLayout formLayout1 = new FormLayout();
        formLayout1.setLabelSeparator("");
        formLayout1.setLabelAlign(LabelAlign.TOP);
        return formLayout1;
    }

    private void onChangeChbxForSale(BaseEvent be) {
        if (chbxForSale.getValue()) {
            nmbrfldPrice.setVisible(true);
            lblfldEuros.setVisible(true);
            lblfldPrice.setVisible(true);
            nmbrfldPrice.setEnabled(true);
        } else {
            nmbrfldPrice.setVisible(false);
            lblfldEuros.setVisible(false);
            lblfldPrice.setVisible(false);
            nmbrfldPrice.setEnabled(false);
        }
    }

    private void initBasicFieldSet() {
        fldstBasic = new FieldSet();
        fldstBasic.addListener(Events.BeforeExpand,
                new Listener<FieldSetEvent>() {
                    public void handleEvent(FieldSetEvent e) {
                        fieldSetExpand(e);
                    }
                });
        FormLayout flFldstBasic = newFormLayout();
        flFldstBasic.setDefaultWidth(700);

        fldstBasic.setLayout(flFldstBasic);

        txtfldTitle = new TextField();
        txtfldTitle.setAllowBlank(false);
        txtfldTitle.setSelectOnFocus(true);
        txtfldTitle.setMinLength(5);
        txtfldTitle.setMaxLength(100);
        txtfldTitle.setName("title");
        txtfldTitle.setFieldLabel("title");
        fldstBasic.add(txtfldTitle);
        txtfldTitle.setSize("700px", "20px");

        htmldtrDetail = new HtmlEditor();
        htmldtrDetail.setName("description");
        fldstBasic.add(htmldtrDetail);
        htmldtrDetail.setSize("700px", "250px");
        htmldtrDetail.setFieldLabel("description");

        frmpnlArtwork.add(fldstBasic);
        fldstBasic.setHeading("Basic");
        fldstBasic.setCollapsible(true);

    }

    private void fieldSetExpand(FieldSetEvent e) {
        FieldSet fsToExpand = e.getFieldSet();
        if (fsToExpand != fldstBasic) {
            fldstBasic.setExpanded(false);
        }
        if (fsToExpand != fldstDetail) {
            fldstDetail.setExpanded(false);
        }
        if (fsToExpand != fldstPhotos) {
            fldstPhotos.setExpanded(false);
        }
        frmpnlArtwork.layout();
    }

    private void addArtworkToProjectAsync(Long projectId, Long artworkId) {
        projectController.addArtworkToProject(projectId, artworkId,
                new AsyncCallback<Void>() {
                    @Override
                    public void onFailure(Throwable caught) {
                        TopInfo.display("Error", "Unable to add to project");
                    }

                    @Override
                    public void onSuccess(Void result) {
                        TopInfo.display("Info", "Artwork added to project");
                        setProjectsInAddButton();
                    }
                });
    }

    private void addArtworkToExhibitionAsync(Long exhibitionId, Long artworkId) {
        exhibitionController.addArtworkToExhibition(exhibitionId, artworkId,
                new AsyncCallback<Void>() {
                    @Override
                    public void onFailure(Throwable caught) {
                        TopInfo.display("Error", "Unable to add to exhibition");
                    }

                    @Override
                    public void onSuccess(Void result) {
                        TopInfo.display("Info", "Artwork added to exhibition");
                        setExhibitionsInAddButton();
                    }
                });
    }

    private void deleteArtworkFromProjectAsync(Long projectId, Long artworkId) {
        projectController.deleteArtworkFromProject(projectId, artworkId,
                new AsyncCallback<Void>() {
                    @Override
                    public void onFailure(Throwable caught) {
                        TopInfo.display("Error",
                                "Unable to delete from project");
                    }

                    @Override
                    public void onSuccess(Void result) {
                        TopInfo.display("Info", "Artwork deleted from project");
                        setProjectsInAddButton();
                    }
                });
    }

    private void deleteArtworkFromExhibitionAsync(Long exhibitionId,
            Long artworkId) {
        exhibitionController.deleteArtworkFromExhibition(exhibitionId,
                artworkId, new AsyncCallback<Void>() {
                    @Override
                    public void onFailure(Throwable caught) {
                        TopInfo.display("Error",
                                "Unable to delete from exhibition");
                    }

                    @Override
                    public void onSuccess(Void result) {
                        TopInfo.display("Info",
                                "Artwork deleted from exhibition");
                        setExhibitionsInAddButton();
                    }
                });
    }

    private void addArtworkToRoomAsync(String roomKey, Long artworkId) {
        galleryController.addArtworkToRoom(artwork.getId(), roomKey,
                new AsyncCallback<Void>() {
                    @Override
                    public void onFailure(Throwable caught) {
                        TopInfo.display("Error",
                                "Unable to add to gallery room");
                    }

                    @Override
                    public void onSuccess(Void result) {
                        TopInfo.display("Info", "Artwork added to gallery room");
                        setGalleriesInAddButton();
                    }
                });
    }

    private void deleteArtworkFromRoomAsync(String roomKey, Long artworkId) {
        galleryController.deleteArtworkFromRoom(artworkId, roomKey,
                new AsyncCallback<Void>() {
                    public void onFailure(Throwable caught) {
                        TopInfo.display("Error",
                                "Unable to delete from gallery room");
                    }

                    public void onSuccess(Void result) {
                        TopInfo.display("Info",
                                "Artwork deleted from gallery room");
                        setGalleriesInAddButton();
                    }
                });
    }

    private void addProjectsToMenu(List<SelectProject> result) {
        for (SelectProject value : result) {
            MenuItem item = createProjectMenuItem(value);
            btnAddToProject.getMenu().add(item);
        }
        btnAddToProject.setEnabled(true);
    }

    private void addGalleriesToMenu(List<Gallery> result) {
        Log.debug(" > addGalleriesToMenu [" + result.size() + "]");
        for (Gallery value : result) {
            btnAddToGallery.getMenu().add(new Label(value.getTitle()));
            btnAddToGallery.getMenu().add(new Label("--------------"));
            for (Room room : value.getRooms()) {
                MenuItem item = createGalleryRoomMenuItem(room);
                btnAddToGallery.getMenu().add(item);
            }
        }
        btnAddToGallery.setEnabled(true);
    }

    private void addExhibitionsToMenu(List<Exhibition> result) {
        Log.debug(" > addExhibitionsToMenu [" + result.size() + "]");
        for (Exhibition value : result) {
            MenuItem item = createExhibitionMenuItem(value);
            btnAddToExhibition.getMenu().add(item);
        }
        btnAddToExhibition.setEnabled(true);
    }

    private MenuItem createGalleryRoomMenuItem(Room room) {
        MenuItem item = new MenuItem(room.getName());
        item.setItemId(room.getKey());
        boolean hasArtwork = false;
        if (room.getArtworks() != null) {
            for (RoomArtwork roomartwork : room.getArtworks()) {
                if (roomartwork.getArtworkId().equals(artwork.getId())) {
                    hasArtwork = true;
                    break;
                }
            }
        }
        if (hasArtwork) {
            item.setIcon(Resources.ICONS.delete());
            item.addSelectionListener(new SelectionListener<MenuEvent>() {
                @Override
                public void componentSelected(MenuEvent ce) {
                    MenuItem _item = (MenuItem) ce.getItem();
                    String roomKey = _item.getItemId();
                    deleteArtworkFromRoomAsync(roomKey, artwork.getId());
                };
            });
        } else {
            item.addSelectionListener(new SelectionListener<MenuEvent>() {
                @Override
                public void componentSelected(MenuEvent ce) {
                    MenuItem _item = (MenuItem) ce.getItem();
                    String roomKey = _item.getItemId();
                    addArtworkToRoomAsync(roomKey, artwork.getId());
                };
            });
        }
        return item;
    }

    private MenuItem createProjectMenuItem(SelectProject value) {
        MenuItem item = new MenuItem(value.getProjectTitle());
        item.setItemId(value.getProjectId().toString());
        if (value.isHasArtwork()) {
            item.setIcon(Resources.ICONS.delete());
            item.addSelectionListener(new SelectionListener<MenuEvent>() {
                @Override
                public void componentSelected(MenuEvent ce) {
                    MenuItem _item = (MenuItem) ce.getItem();
                    Long projectId = new Long(_item.getItemId());
                    deleteArtworkFromProjectAsync(projectId, artwork.getId());
                };
            });
        } else {
            item.addSelectionListener(new SelectionListener<MenuEvent>() {
                @Override
                public void componentSelected(MenuEvent ce) {
                    MenuItem _item = (MenuItem) ce.getItem();
                    Long projectId = new Long(_item.getItemId());
                    addArtworkToProjectAsync(projectId, artwork.getId());
                };
            });
        }
        return item;
    }

    private MenuItem createExhibitionMenuItem(Exhibition exhi) {
        MenuItem item = new MenuItem(exhi.getTitle());
        item.setItemId(exhi.getId().toString());
        boolean hasArtwork = false;
        if (exhi.getArtworks() != null) {
            for (ExhibitionArtwork exhiartwork : exhi.getArtworks()) {
                if (exhiartwork.getArtworkId().equals(artwork.getId())) {
                    hasArtwork = true;
                    break;
                }
            }
        }
        if (hasArtwork) {
            item.setIcon(Resources.ICONS.delete());
            item.addSelectionListener(new SelectionListener<MenuEvent>() {
                @Override
                public void componentSelected(MenuEvent ce) {
                    MenuItem _item = (MenuItem) ce.getItem();
                    String exhiId = _item.getItemId();
                    deleteArtworkFromExhibitionAsync(new Long(exhiId),
                            artwork.getId());
                };
            });
        } else {
            item.addSelectionListener(new SelectionListener<MenuEvent>() {
                @Override
                public void componentSelected(MenuEvent ce) {
                    MenuItem _item = (MenuItem) ce.getItem();
                    String exhiId = _item.getItemId();
                    addArtworkToExhibitionAsync(new Long(exhiId),
                            artwork.getId());
                };
            });
        }
        return item;
    }
}
